package keyword

import (
	"fmt"
	"reflect"
)

// 定义一个操作数组的接口
type ArrayOption interface {
	// 数组或切片去重
	unique(slice []interface{}) []interface{}
	// 两个数组取差
	difference(slice1, slice2 []interface{}) []interface{}
}

// 数组的结构体
type arrayOption struct {
	desc string
}

// 数组去重
func (a *arrayOption) unique(slice []interface{}) []interface{} {
	fmt.Println("--------------", a.desc, "-----------------")
	// 初始化一个map
	seen := make(map[interface{}]bool)
	// 初始化一个泛型数组
	var uniqueSlice []interface{}
	// 循环参数列表，利用map的key值唯一性进行去重
	for _, v := range slice {
		if _, ok := seen[v]; !ok {
			seen[v] = true
			uniqueSlice = append(uniqueSlice, v)
		}
	}
	fmt.Printf("去重前:%v,\n去重后:%v\n", slice, uniqueSlice)
	return uniqueSlice
}

// 数组取差
func (a *arrayOption) difference(slice1, slice2 []interface{}) []interface{} {
	fmt.Println("--------------", a.desc, "-----------------")
	if len(slice1) != len(slice2) {
		panic("slices1 and slices2 are not the same length")
	}
	if reflect.TypeOf(slice1[0]) != reflect.TypeOf(slice2[0]) {
		panic("slices1 and slices2 are not the types")
	}
	// 初始化一个map
	seen := make(map[interface{}]bool)
	var differenceSlice []interface{}
	// 将slice1对应值存入到map中
	for _, v := range slice1 {
		if _, ok := seen[v]; !ok {
			seen[v] = true
		}
	}
	for _, v := range slice2 {
		if _, ok := seen[v]; !ok {
			differenceSlice = append(differenceSlice, v)
		}
	}
	return differenceSlice
}

// 实现接口方法
func ArrayUniqueOption(A ArrayOption, slice []interface{}) []interface{} {
	return A.unique(slice)
}

// 调用实现数组求差的方法
func ArrayDifferenceOption(A ArrayOption, slice1, Slice2 []interface{}) []interface{} {
	return A.difference(slice1, Slice2)
}

// 操作去重
func option_unique() {
	var A ArrayOption
	// 定义值类型为int的数组
	intArray := []interface{}{1, 2, 3, 4, 5, 5, 6, 6, 77, 9}
	stringArray := []interface{}{"a", "b", "c", "d", "e", "f", "g", "a", "b", "c"}
	// 实例化结构体
	option := &arrayOption{desc: "数组去重操作"}
	A = option
	// 调用接口
	ArrayUniqueOption(A, stringArray)
	ArrayUniqueOption(A, intArray)
}

// 数组之间求差
func option_difference() {
	var A ArrayOption
	intArray1 := []interface{}{1, 2, 3, 4, 5, 5, 6, 6, 77, 9}
	intArray2 := []interface{}{1, 2, 3, 4, 5, 5, 6, 6, 88, 99}
	// 实例化结构体
	option := &arrayOption{
		desc: "两个数组之前求差",
	}
	// 调用接口处理
	A = option
	result := ArrayDifferenceOption(A, intArray1, intArray2)
	fmt.Println(result)
}

// 主执行方法
func ArrayInitRun() {
	// 数组去重
	option_unique()
	// 数组求差
	option_difference()
}
